package com.sinodata.bsm.cicp.collector.common;

import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.Collector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.CommandReader;
import com.sinodata.bsm.common.constants.SeparatorConstants;
import com.sinodata.bsm.common.vo.ResPropertyValue;

/**
 * 
 * <p>
 * Description: 用户登录列表采集程序 通过shell命令采集 返回登录列表
 * </p>
 *
 * @author liulibo
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-12-20 15:33:38      liulibo        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class LoginListCollector extends Collector {

    private static final Logger logger = Logger.getLogger(LoginListCollector.class);

    // static String col = Constants.COL_SEPRATOR;
    static String col = SeparatorConstants.COL_SEPARATOR;
    //static String lin = Constants.LINE_SEPERATOR;
    static String lin = SeparatorConstants.LIN_SEPARATOR;
    static final String TMP_KEY = "^^^";

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        String cmd = this.paramMap.get("currentUserCmd");
        String cmdStr = this.paramMap.get("userOperCmd");
        List<ResPropertyValue> list = collectWho(ip, cmd, cmdStr);
        return list;
    }

    @Override
    public String[] getParamMeta() {
        return new String[] { "currentUserCmd", "userOperCmd" };
    }

    @Override
    public String[] getPropMeta() {
        return new String[] { "userLists" };
    }

    private List<ResPropertyValue> collectWho(String ip, String cmd, String cmdStr) throws CollectorException {
        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();
        String[] propMetas = getPropMeta();
        Hashtable whatHash = collectWhat(ip, cmdStr);
        StringBuffer sb = new StringBuffer();
        //        sb.append("用户名");
        //        sb.append("UserName");
        //        sb.append(SeparatorConstants.COL_SEPARATOR);
        //        //        sb.append("终端");
        //        sb.append("Terminal");
        //        sb.append(SeparatorConstants.COL_SEPARATOR);
        //        //        sb.append("登陆时间");
        //        sb.append("LoginTime");
        //        sb.append(SeparatorConstants.COL_SEPARATOR);
        //        sb.append("IP/HOST");
        //        sb.append(SeparatorConstants.COL_SEPARATOR);
        //        //        sb.append("操作");
        //        sb.append("Operation");
        //        sb.append(SeparatorConstants.COL_SEPARATOR);
        //        sb.append(SeparatorConstants.LIN_SEPARATOR);
        BufferedReader reader = null;
        try {
            // 获取输入流
            reader = CommandReader.getReader(ip, cmd, (int) this.interval, 0);
            // reader读入的每行数据
            String strLine = null;

            while (true) {

                strLine = reader.readLine();
                if (strLine == null) {
                    break;
                } else {
                    strLine = strLine.trim();
                    if (strLine.length() > 0) {
                        sb.append(formatLine(strLine, whatHash));
                    }
                }
            }
            String str = sb.toString().trim();
            ResPropertyValue propertyValueX = new ResPropertyValue();
            ResPropertyValue.PropValue[] propValues = new ResPropertyValue.PropValue[1];
            propValues[0] = ResPropertyValue.createPropValue(str, propMetas[0]);
            propertyValueX.setValues(propValues);
            values.add(propertyValueX);
        } catch (Throwable t) {
            logger.error("failed to collect who", t);
            throw new CollectorException(t);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (java.io.IOException e) {
                    logger.error("failed to close BufferedReader", e);
                }
            }
        }
        return values;
    }

    /**
     * 调用"w -w"命令,采集到所有用户的what字段
     *
     * @return Hashtable,key是:user + "^^^" + tty 当采集失败时,返回null
     * @throws CollectorException
     */
    private Hashtable collectWhat(String ip, String cmdStr) throws CollectorException {
        BufferedReader reader = null;
        Hashtable retHash = new Hashtable();
        try {
            // 获取输入流
            //			reader = CollectorUtil.getReader(cmdStr, ip);
            reader = CommandReader.getReader(ip, cmdStr, (int) this.interval, 0);
            // reader读入的每行数据
            String strLine = null;
            // 该用户当前的执行命令
            String whatLine = null;
            String user = null;
            String tty = null;
            // what的index
            int index = -1;

            // 先跳过第1行
            strLine = reader.readLine();
            if (strLine == null || strLine.trim().equals("")) {
                return null;
            }
            // 从第2行中获取index
            strLine = reader.readLine();
            if (strLine == null || strLine.trim().equals("")) {
                return null;
            }
            index = strLine.indexOf("what");
            if (index == -1) {
                index = strLine.indexOf("WHAT");
            }
            // //////// lxz added, 2005-05-19,处理SCO情况
            if (index == -1) {
                index = strLine.indexOf("What");
            }
            // //////// end of lxz added

            if (index == -1) {
                logger.warn("index of 'what' is -1,error occurs when run 'w -w' on solaris,hp,aix,tru64 or 'w -f' on linux");
                return null;
            }
            // 开始循环获取数据
            while (true) {
                strLine = reader.readLine();
                if (strLine == null || strLine.trim().equals("")) {
                    break;
                }

                // 获取user,tty
                StringTokenizer st = new StringTokenizer(strLine);
                try {
                    user = st.nextToken();
                    tty = st.nextToken();
                    whatLine = strLine.substring(index).trim();
                    retHash.put(user + TMP_KEY + tty, whatLine);
                } catch (Throwable t) {
                    continue;
                }
            }
        } catch (Throwable t) {
            logger.error("failed to collect what", t);
            throw new CollectorException(t);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception e) {
                    logger.error("failed to close BufferedReader", e);
                }
            }
        }
        return retHash;
    }

    /**
     * 在一行的各列中以COL_SEPRATOR分割
     *
     * "abis pts/5 Aug 02 08:40 (137.224.254.191)"
     *
     * @return
     * @throws CollectorException
     */
    private static String formatLine(String line, Hashtable whatHash) throws CollectorException {
        Pattern pattern = Pattern.compile("(\\S+)\\s+(\\S+)\\s+(.+)\\s+\\((\\S+)\\)");
        Pattern patternx = Pattern.compile("(\\S+)\\s+(\\S+)\\s+(.+)");
        StringBuffer sb = new StringBuffer();
        try {
            Matcher matcher = pattern.matcher(line);
            Matcher matcherx = patternx.matcher(line);
            if (matcher.find()) {
                String user = matcher.group(1);
                String tty = matcher.group(2);
                sb.append(matcher.group(1));
                sb.append(SeparatorConstants.COL_SEPARATOR);
                sb.append(matcher.group(2));
                sb.append(SeparatorConstants.COL_SEPARATOR);
                sb.append(matcher.group(3));
                sb.append(SeparatorConstants.COL_SEPARATOR);
                sb.append(matcher.group(4));
                sb.append(SeparatorConstants.COL_SEPARATOR);
                if ((whatHash != null) && (whatHash.get(user + TMP_KEY + tty) != null)) {
                    sb.append(whatHash.get(user + "^^^" + tty));
                } else {
                    sb.append("<UNKNOWN>");
                }
                sb.append(SeparatorConstants.COL_SEPARATOR);
                sb.append(SeparatorConstants.LIN_SEPARATOR);
            } else if (matcherx.find()) {
                String user = matcherx.group(1);
                String tty = matcherx.group(2);
                sb.append(matcherx.group(1));
                sb.append(SeparatorConstants.COL_SEPARATOR);
                sb.append(matcherx.group(2));
                sb.append(SeparatorConstants.COL_SEPARATOR);
                sb.append(matcherx.group(3));
                sb.append(SeparatorConstants.COL_SEPARATOR);
                sb.append("<UNKNOWN>");
                sb.append(SeparatorConstants.COL_SEPARATOR);
                if ((whatHash != null) && (whatHash.get(user + TMP_KEY + tty) != null)) {
                    sb.append(whatHash.get(user + "^^^" + tty));
                } else {
                    sb.append("<UNKNOWN>");
                }
                sb.append(SeparatorConstants.COL_SEPARATOR);
                sb.append(SeparatorConstants.LIN_SEPARATOR);
            }
        } catch (Throwable t) {
            logger.error("failed to format line", t);
            throw new CollectorException(t);
        }
        return sb.toString();
    }

}
